Paste number 15241: | wow_menu |
Pasted by: | kdix |
When: | 19 years, 2 months ago |
Share: | Tweet this! | http://paste.lisp.org/+BRD |
Channel: | None |
Paste contents: |
// ---------------------------------------------------- function wow_menu($atts) { // <txp:wow_menu start="root" hide="15" showparent="1" /> // Analyze tag extract(lAtts(array( 'start' => 'root', 'hide' => '', 'showparent' => '1', ),$atts)); $menuRendered = displayMenu($start, $hide, $showparent); return($menuRendered); } // ---------------------------------------------------- // Add a new tab to the Content area. if (@txpinterface == 'admin') { $myevent = 'menu_control'; $mytab = 'Menu control'; // Set the privilege levels for our new event add_privs($myevent, '1,2'); // Add a new tab under 'extensions' associated with our event register_tab("extensions", $myevent, $mytab); // Register wow_menu_control as callback function register_callback("wow_menu_control", $myevent); } function wow_menu_control($event, $step) { pagetop("Menu Control"); echo <<<CSS_BLOCK <style type="text/css"> h1 { text-align:center; } #menubox { width:500px; text-align:center; margin-left:auto; margin-right:auto; } #menutree { text-align:left; margin-left:-30px; } #menubox a { font-weight:bold; font-size:14px; } #menutree li, #menutree li li, #menutree li li li, #menutree li li li li { margin:1px; list-style-type:none; } #menutree li { background:#eee; } #menutree li li { background:#ddd; } #menutree li li li { background:#ccc; } #menutree li li li li { background:#bbb; } </style> CSS_BLOCK; print("<div id=\"menubox\">\n"); print("<h1>Menu Control</h1>\n"); if ($step != 2) { print('<p>Below you see all your menu items together with their [ID]. To change the order of the items, use the ⇑ and ⇓ icons. This will move the current item AND all its child elements up and down the tree.</p>'); // WARNING: DO NOT ALTER THE JAVASCRIPT BLOCK UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING! // These four JavaScript functions contain the menu item shifting logic which directly alters the DOM tree of the menu as a list. echo <<<SCRIPT_BLOCK <script type="text/javascript"> function move(dir,id){activeNode=document.getElementById(id);if(dir=="up"){relNode=previousNodeSibling(activeNode);if(!relNode)relNode=activeNode;}else relNode=nextNodeSibling(activeNode);parent=activeNode.parentNode;if(!((!relNode)&&(dir == "up")))parent.insertBefore(activeNode,relNode);return;} function previousNodeSibling(node){res=node.previousSibling;while((res !=null)&&(res.nodeType!=1))res=res.previousSibling;return res;} function nextNodeSibling(node){res=node.nextSibling;rescount=0;while((res)&&((res.nodeType!=1)||(rescount<1))){if(res.nodeType==1)rescount++;res=res.nextSibling;}return res;} function finalize(){element_count=document.getElementsByTagName("li").length;i=0;pass_on='';while(i<element_count){pass_on+=document.getElementsByTagName("li")[i++].id;if(i<element_count)pass_on+=",";}document.menu_result.menu_order.value=pass_on;document.menu_result.submit();} </script> SCRIPT_BLOCK; // Check if "idx" field exists $querystring = "show columns from ".PFX."txp_category like 'idx';"; $field_exists = getRow($querystring); if(!$field_exists) { // Create field idx for storing the menu item orderID print("<p>Field status: Menu item order ID field <strong>NOT found</strong> - attempting to create it...</p>\n"); $return_value = safe_alter("txp_category","ADD idx INT;"); if($return_value) print("<p>Field successfully created.</p>\n"); else die("<p style=\"color:#f00\">Error creating field! Please create field 'idx' (type INT, default NULL) in table <PREFIX>txp_category manually and try again.</p>\n"); } else print("<p>Field status: Menu item order ID field found.</p>\n"); $root_elements = safe_rows("id,name,type,parent,title","txp_category","name != 'root' and type = 'article' and parent = 'root' order by idx"); print("<div id=\"menutree\"><ul>"); foreach($root_elements as $root_item) getChildren($root_item); print("</ul></div>"); print('<form name="menu_result" action="index.php" method="post">'); print('<input type="hidden" name="menu_order" value="" />'); print('<input type="hidden" name="event" value="menu_control" /><input type="hidden" name="step" value="2" />'); print('<A style="background:#FFFF99;padding:4px;padding:3px;margin-top:20px;border:solid 2px #FFCC33;" HREF="javascript:finalize()">SAVE CHANGES</a></form>'); print('<p style="margin-top:20px;padding:10px;font-weight:bold;border-bottom:solid 1px;">wow-Menu Explanation</p> <p>The number in square brackets shows the ID of the item as set in the database, e.g. [15]. If you want to hide a menu item and its child elements, pass on the ID of this item when calling the wow_menu plugin from within your template code. For example, use <txp:wow_menu hide="15" />. By adding more comma-separated values, you can hide more items.</p> <p>You can also set the starting ("root") element if you would like to just display a part of the tree, for example if it is too complex to display all items on the front page. To do so, add the <i>start</i> attribute to the wow_menu call, like so: <txp:wow_menu start="my-category" />. The given category name will set the starting element for the tree, displaying all child elements, but none on the same level or above of the root element. The default value is "root".</p> <p>You may use <i>showparent</i> in connection with <i>start</i> to determine if the start element should be displayed before the child elements (1), or just the child elements alone (0).</p> <p>Both <i>start</i> and <i>hide</i> attributes may be combined in the plugin call, but please make sure the combination is logically sound - otherwise the script will crash as it\'s not fool-proof. :)</p> <p style="border-bottom:solid 1px;padding-bottom:10px;">Comments welcome: <A style="font-size:11px" HREF="mailto:schwenzer@nightworks.de?subject=wow_menu">Send me an e-mail</a>.</p> '); } else { // Get postvars $menuitem_order = explode(",",ps("menu_order")); // First, reset the previous order by inserting NULL into the idx database field safe_update("txp_category","idx = NULL", "1"); // Update the idx - the consecutive number of the menu items - in the db foreach($menuitem_order as $name => $value) safe_update("txp_category","idx = $name", "id = $value"); print("New menu order successfully saved.\n"); $menuRendered = displayMenu("root",""); print($menuRendered); } print("</div>"); } function displayMenu($root_item, $deny, $showparentitem) { // Now, retrieve the ordered menu item list from the db $menuitems_ordered = safe_rows("id,name,type,parent,title,idx","txp_category","idx is not NULL order by idx"); $ids_denied = explode(",",$deny); if ($deny) { $menuitems_denied = array(); foreach ($ids_denied as $j) { $temp = safe_row("name","txp_category","id = $j"); $menuitems_denied[] = $temp['name']; } } // Initialize output variable and initialize menu tree structure $output = "<div id=\"menutree\"><ul>"; // Initialize path array, which will store the parent item names and always contain the up-to-date path to an item $path = array(); // Set defaults $item_start = 0; $path[0] = "root"; // Let's remember the last active path - needed when the "hide" attribute ($deny values) is in use $lastactivepath = $path; // Since no item has been displayed yet, set to false $firstitemdisplayed = false; $modifier = 1; // The "modifier" is used to alter some counting offsets which need to be "1" if we're looking at the full tree. // If a subtree is to be displayed, the modifier needs to be "2". The reason is the path length: If we're looking at // a subtree, the path will always contain "root" as first element, and then the root_item's name (no matter how many nodes are in between). // This means that for a full tree, the minimum path length is 1 (root), and 2 for a subtree (root/root_item). if ($root_item != "root") { // If the start item isn't root, find out the orderID of the root element foreach($menuitems_ordered as $x) if ($x['name'] == $root_item) $item_start = $x['idx']; $path[1] = $root_item; // Only print root element if $showparentitem is set to 1 if ($showparentitem) $output .= "<li><a href=\"index.php?c=" . $menuitems_ordered[$item_start]['name'] . "\">" . $menuitems_ordered[$item_start]['title'] . "</a><ul>\n"; $modifier = 2; $start_parent = $menuitems_ordered[$item_start]['parent']; $item_start++; } for($item_count = $item_start; $item_count < count($menuitems_ordered); $item_count++) { // Fetch item we'll work with in this iteration $item = $menuitems_ordered[$item_count]; $output_temp = ""; if (($root_item != "root") && ($item['parent'] == $start_parent)) break; if ($item['parent'] == $root_item) { // If it's a root item and the path already contains values (i.e. the previous item wasn't root), close all previously created branches if(count($path) > $modifier) for ($i = $modifier; $i < count($path); $i++) $output_temp .= "</li></ul>\n"; // Now, kill the path - we have a root element, there are no parents. $path = array_slice($path, 0, $modifier); // if ($root_item != "root") $path[] = $root_item; // Special case for the for the very first element - there hasn't been an opening <li> tag yet, so don't close it // if ($item['idx'] != 0) $output_temp .= "</li>"; if ($firstitemdisplayed) $output_temp .= "</li>"; } else if (!in_array($item['parent'], $path)) { // If it's not in the path, put it in! $path[] = $item['parent']; // We have just created a new branch - insert the <ul> for that. $output_temp .= "<ul>"; } else { // This block will be accessed when an item's parent is in the array - this means we're on the same branch or jumped up a few levels. // Let's find out which ID of the path array contains out parent. $id_exists = array_search($item['parent'], $path); // If we went some levels up in the tree, we need to know how many. $levels_up = count($path) - ($id_exists + 1); // If we have a levels_up, close a branch for each levels_up if ($levels_up > 0) for ($i = 0; $i < $levels_up; $i++) $output_temp .= "</li></ul>\n"; // If we didn't jump any levels, well... just close the previous <li> tag. else $output_temp .= "</li>\n"; // Cut away anything in the path array below the current parent (not checking if it's necessary or not, just do it) $path = array_slice($path, 0, $id_exists + 1); } // Ah - finally, the output of the element! $output_temp .= "<li><a href=\"index.php?c=$item[name]\">$item[title]</a>"; if($deny) { // If there are "deny" value(s), check if the current item is or the current path contains the forbidden item IDs. Only use $output_temp if this is not the case. if ((!array_intersect($menuitems_denied, $path)) && (!in_array($item['name'], $menuitems_denied))) { if ($denyactive) { // If this is the first visible item after a number of hidden items, do: $leveldiff = count($path) - count($lastactivepath); // If the current path level does not equal the one we kept in memory, we've jumped. Correct the tree accordingly. if ($leveldiff > 0) $output .= "<ul>"; if ($leveldiff < 0) for ($k = 0; $k < abs($leveldiff); $k++) $output .= "</li></ul>\n"; // firstitemdisplayed makes sure we don't close a <li> before the first item has opened it. if (($leveldiff == 0) && ($firstitemdisplayed)) $output .= "</li>"; $output .= "<li><a href=\"index.php?c=$item[name]\">$item[title]</a>"; $denyactive = false; } else { $output .= $output_temp; $lastactivepath = $path; $firstitemdisplayed = true; } } else $denyactive = true; // Flag to mark that items are being suppressed } else { $output .= $output_temp; $firstitemdisplayed = true; $lastactivepath = $path; } } // Close any branches which we left open, determined by the length of the path array. if ($showparentitem) for ($x = 1; $x <= count($lastactivepath); $x++) $output .= "</li></ul>"; // Even if the parent item wasn't shown, it's still in the path, so return one </li></ul> less else for ($x = 2; $x <= count($lastactivepath); $x++) $output .= "</li></ul>"; // Ooops... don't forget to close the DIV tag which contains the menu! $output .= "</div>"; return($output); } function getChildren($parent_item) { $parent = $parent_item['name']; $menu_items = safe_rows("id,name,type,parent,title","txp_category","name != 'root' and type = 'article' and parent = '$parent' order by idx"); print("<li id=\"$parent_item[id]\">$parent_item[title] [$parent_item[id]] <a href=\"javascript:move('up',$parent_item[id])\">⇑</a> <a href=\"javascript:move('down',$parent_item[id])\">⇓</a>"); if(!$menu_items) print("</li>\n"); else { print("\n<ul>\n"); foreach($menu_items as $x) getChildren($x); print("</ul>\n</li>\n"); } }
This paste has no annotations.